package top.hekun.study.core.visitor.simple;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;
import top.hekun.study.core.util.MyMethodVisitor5Util;

import java.io.PrintStream;

import static org.objectweb.asm.Opcodes.*;
import static top.hekun.study.core.ClassSimpleModifyClassDemo.ERROR_CODE;

/**
 * 〈增加方法〉
 *
 * @author: Sakura
 * @date: 2023/5/8
 */
public class MyClassVisitor7 extends ClassVisitor {
    private String thisClassName = this.getClass().getSimpleName();
    private boolean isMethodPresent;
    public MyClassVisitor7(int apiVersion, ClassVisitor classWriter) {
        super(apiVersion, classWriter);
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        System.out.println(thisClassName +" visit");
        super.visit(version, access, name, signature, superName, interfaces);
    }
    @Override
    public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
        System.out.println(thisClassName +" visitField -- " + name);
        return super.visitField(access, name, descriptor, signature, value);
    }
    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        System.out.println(thisClassName +" visitMethod -- " + name + " -- " + descriptor);
        if ("testAdd".equals(name)&& "(II)V".equals(descriptor)){
            isMethodPresent = true;
        }
        return super.visitMethod(access, name, descriptor, signature, exceptions);
    }
    @Override
    public void visitEnd() {
        System.out.println(thisClassName +" visitEnd");
        if (!isMethodPresent) {
            // 添加方法
            // 根据方法调用顺序可知, visitMethod在visitEnd() 前调用
            MethodVisitor methodVisitor = super.visitMethod(ACC_PRIVATE , "testAdd", "(II)V", null, null);
            if (methodVisitor != null) {
                generateCode(methodVisitor);
            }
        }
        super.visitEnd();
    }

    /**
     * 编写方好体
     * @param methodVisitor
     */
    private void  generateCode(MethodVisitor methodVisitor){

        Method method = Method.getMethod("void testAdd (int,int)");
        GeneratorAdapter generatorAdapter = new GeneratorAdapter(ACC_PRIVATE,method,methodVisitor);
        generatorAdapter.visitCode();
        // 编写代码体
        generatorAdapter.getStatic(Type.getType(System.class),"out",Type.getType(PrintStream.class));
        generatorAdapter.push(thisClassName +",GeneratorAdapter生成!!");
        generatorAdapter.invokeVirtual(Type.getType(PrintStream.class),Method.getMethod("void println (String)"));
        generatorAdapter.visitLdcInsn(1);
        generatorAdapter.loadArg(0);
        generatorAdapter.invokeStatic(Type.getType(MyMethodVisitor5Util.class),Method.getMethod("void parameterPrintln (int,int)"));

        generatorAdapter.returnValue();
        generatorAdapter.endMethod();
    }
}
